package com.jinke.api.modules.app.controller;


import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.jinke.api.common.annotation.OrderApiIdempotence;
import com.jinke.api.common.api.CommonPage;
import com.jinke.api.common.api.CommonResult;
import com.jinke.api.common.util.CommonUtil;
import com.jinke.api.common.util.Global;
import com.jinke.api.modules.app.enums.OrderStatus;
import com.jinke.api.modules.app.enums.OrderType;
import com.jinke.api.modules.app.model.Order;
import com.jinke.api.modules.app.model.OrderParcel;
import com.jinke.api.modules.app.model.SysCity;
import com.jinke.api.modules.app.model.SysState;
import com.jinke.api.modules.app.request.*;
import com.jinke.api.modules.app.response.BatchEstimateRateResponse;
import com.jinke.api.modules.app.response.EstimateRateOrderResponse;
import com.jinke.api.modules.app.response.GetOrdersResponse;
import com.jinke.api.modules.app.service.OrderParcelService;
import com.jinke.api.modules.app.service.OrderService;
import com.jinke.api.modules.app.service.SysCityService;
import com.jinke.api.modules.app.service.SysStateService;
import com.jinke.api.modules.app.util.OssUtil;
import com.jinke.api.modules.base.service.BaseShipService;
import com.jinke.api.modules.base.service.ShipFactory;
import com.jinke.api.modules.third.ezeeship.model.request.EstimateRateRequest;
import com.jinke.api.modules.third.ezeeship.model.response.CreateLabelResponse;
import com.jinke.api.modules.ums.model.Channel;
import com.jinke.api.modules.ums.model.UmsAdmin;
import com.jinke.api.modules.ums.model.UserChannel;
import com.jinke.api.modules.ums.service.ChannelService;
import com.jinke.api.modules.ums.service.UserChannelService;
import com.jinke.api.modules.ums.util.UserUtil;
import com.jinke.api.security.util.AdminUserUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 承运商平台 前端控制器
 * </p>
 *
 * @author macro
 * @since 2024-01-15
 */
@RestController
@Api(tags = "订单")
@Tag(name = "订单", description = "订单")
@RequestMapping("/app/order")
@Slf4j
public class OrderController {

    @Resource
    private OrderService orderService;
    @Resource
    private ShipFactory shipFactory;
    @Resource
    private UserChannelService userChannelService;
    @Resource
    private ChannelService channelService;
    @Autowired
    private SysCityService sysCityService;
    @Autowired
    private SysStateService sysStateService;
    @Resource
    private OssUtil ossUtil;
    @Resource
    private OrderParcelService orderParcelService;


    @ApiOperation("费率估算")
    @RequestMapping(value = "/estimateRate", method = RequestMethod.POST)
    @ResponseBody
    public CommonResult<EstimateRateOrderResponse> estimateRate(@RequestBody EstimateRateRequest request) {
        //统一处理数据
        CommonUtil.handle(request);
//        return orderService.estimateRateNew(request);

        return orderService.estimateRate(request);


    }


    @ApiOperation("另存为草稿")
    @RequestMapping(value = "/draft", method = RequestMethod.POST)
    @ResponseBody
    public CommonResult<EstimateRateOrderResponse> draft(@RequestBody EstimateRateRequest request) {
        return orderService.draft(request);
    }

    @ApiOperation("作废还原成草稿")
    @RequestMapping(value = "/cancelRestore", method = RequestMethod.POST)
    public CommonResult<String> draftRestore(@RequestBody @Validated OrderCancelRequest request) throws IOException {
        UmsAdmin userInfo = AdminUserUtil.getUserInfo();
        Integer userId = userInfo.getId();
        List<String> orderIds = request.getOrderIds();

        LambdaQueryWrapper<Order> queryWrapper = new LambdaQueryWrapper<Order>()
                .in(Order::getId, orderIds)
                .eq(Order::getStatus, OrderStatus.VOIDED.getValue())
                .orderByDesc(Order::getId);
        // 管理员看所有数据
        if (!userInfo.isAdmin()) {
            queryWrapper.eq(Order::getUserId, userId);
        }
        List<Order> orders = orderService.list(queryWrapper);

        if (CollectionUtil.isEmpty(orders)) {
            return CommonResult.success();
        }
        orders.forEach(x -> {
            x.setStatus(OrderStatus.DRAFT.getValue());
        });
        orderService.updateBatchById(orders);

        return CommonResult.success();

    }

    @ApiOperation("批量费率估算")
    @RequestMapping(value = "/batchEstimateRate", method = RequestMethod.POST)
    @ResponseBody
    public CommonResult<List<BatchEstimateRateResponse>> batchEstimateRate(@RequestBody BatchEstimateRateRequest request) {
        UmsAdmin userInfo = AdminUserUtil.getUserInfo();
//        return orderService.batchEstimateRateNew(request);
        return orderService.batchEstimateRate(request);


    }

    @ApiOperation("费率计算器")
    @RequestMapping(value = "/estimateRateCalc", method = RequestMethod.POST)
    @ResponseBody
    public CommonResult<EstimateRateOrderResponse> estimateRateCalc(@RequestBody EstimateRateCalcRequest request) {
        Integer userId = AdminUserUtil.getUserId();
        // 获取用户权限
        List<UserChannel> userChannels = userChannelService.list(new LambdaQueryWrapper<UserChannel>()
                .eq(UserChannel::getUserId, userId)
        );
        if (CollectionUtil.isEmpty(userChannels)) {
            return CommonResult.failed("no user channel");
        }

        //根据渠道id 获取渠道列表
        List<Channel> channels = channelService.list(new LambdaQueryWrapper<Channel>()
                .in(Channel::getId, userChannels.stream().map(UserChannel::getChannelId).collect(Collectors.toList()))
        );
        if (CollectionUtil.isEmpty(channels)) {
            return CommonResult.failed("channel not exist already");
        }

        EstimateRateRequest estimateRateRequest = new EstimateRateRequest();
        String fromZipCode = request.getFromZipCode();
        EstimateRateRequest.Address from = getAddress(fromZipCode);
        String toZipCode = request.getToZipCode();
        EstimateRateRequest.Address to = getAddress(toZipCode);
        estimateRateRequest.setFrom(from);
        estimateRateRequest.setTo(to);
        EstimateRateRequest.Parcel parcel = new EstimateRateRequest.Parcel();
        BeanUtils.copyProperties(request, parcel);
        parcel.setPackageCode("your_package");
        estimateRateRequest.setParcels(Arrays.asList(parcel));


        return estimateRate(estimateRateRequest);
    }

    @NotNull
    private EstimateRateRequest.Address getAddress(String fromZipCode) {
        EstimateRateRequest.Address from = new EstimateRateRequest.Address();

        SysCity sysCity = sysCityService.getOne(new LambdaQueryWrapper<SysCity>().eq(SysCity::getZipCode, fromZipCode));
        if (sysCity != null) {

            Integer stateId = sysCity.getStateId();
            SysState sysState = sysStateService.getById(stateId);
            String stateCode = sysState.getStateCode();
            from.setStateCode(stateCode);
            from.setCity(sysCity.getCityName());
            from.setCountryCode("US");
            from.setPersonName("sender");
            from.setZipCode(fromZipCode);
            from.setAddressLine1("2000 Alpine Way");
        }
        return from;
    }

    @ApiOperation("生成面单")
    @RequestMapping(value = "/label/create", method = RequestMethod.POST)
    @ResponseBody
    @OrderApiIdempotence(expireTime = 10)
    public CommonResult<String> createLabel(@RequestBody @Validated EstimateRateRequest request) {
        //统一处理数据
        CommonUtil.handle(request);
        request.setOrderType(OrderType.CREATE);

        return orderService.createLabel(request);
    }

    @ApiOperation("批量下载面单")
    @RequestMapping(value = "/label/down", method = RequestMethod.GET)
    @ResponseBody
    public CommonResult<String> downLabel(@Validated OrderCancelRequest request) {
        UmsAdmin userInfo = AdminUserUtil.getUserInfo();
        Integer userId = userInfo.getId();
        request.setUserId(userId);
        return orderService.downLabel(request);
    }

    @ApiOperation("批量单个下载面单")
    @RequestMapping(value = "/label/downZip", method = RequestMethod.GET)
    @ResponseBody
    public CommonResult<String> downLabel2(@Validated OrderExportsRequest request) {
        request.setUserId(UserUtil.getUserInfo().getId());
        return orderService.downLabel2(request);
    }

    @ApiOperation("批量下载订单")
    @RequestMapping(value = "/order/down", method = RequestMethod.GET)
    public CommonResult<String> download(@Validated OrderExportsRequest request) {
        request.setUserId(UserUtil.getUserInfo().getId());
        return orderService.download(request);
    }

    /**
     * 复制为新订单
     * @param request
     * @return
     * @throws IOException
     */
    @ApiOperation("复制为新订单")
    @RequestMapping(value = "/order/copy", method = RequestMethod.POST)
    public CommonResult<String> copy(@Validated @RequestBody OrderCopyRequest request) throws IOException {
        UmsAdmin userInfo = AdminUserUtil.getUserInfo();
        Integer userId = userInfo.getId();
        request.setUserId(userId);
        return orderService.copy(request);

    }

    @ApiOperation("批量下单")
    @RequestMapping(value = "/label/batchCreate", method = RequestMethod.POST)
    @ResponseBody
    public CommonResult<String> batchCreate(@RequestBody @Validated BatchCreateLabelOrderRequest request) {

        Integer userId = AdminUserUtil.getUserId();
        request.setUserId(userId);
        //return orderService.batchCreate(request);
        return orderService.batchOld(request);
    }


    @ApiOperation("订单列表")
    @RequestMapping(value = "/orders", method = RequestMethod.GET)
    @ResponseBody
    public CommonResult<CommonPage<GetOrdersResponse>> orders(@Validated OrderExportsRequest request) {
        UmsAdmin userInfo = AdminUserUtil.getUserInfo();
        Integer userInfoId = userInfo.getId();
        request.setUserId(userInfoId);
        CommonPage<GetOrdersResponse> data = orderService.getGetOrdersResponseCommonPage(request);
        return CommonResult.success(data);
    }


    @ApiOperation("订单详情")
    @RequestMapping(value = "/orders/detail", method = RequestMethod.GET)
    @ResponseBody
    public CommonResult<GetOrdersResponse> detail(@Validated OrderDetailRequest request) {
        UmsAdmin userInfo = AdminUserUtil.getUserInfo();
        Integer userInfoId = userInfo.getId();
        request.setUserId(userInfoId);
        return orderService.detail(request);
    }

/*    @ApiOperation("草稿订单详情")
    @RequestMapping(value = "/orders/draftDetail", method = RequestMethod.GET)
    @ResponseBody
    public CommonResult<GetOrdersResponse> draftDetail(@Validated OrderDetailRequest request) {


        LambdaQueryWrapper<Order> wrapper = new LambdaQueryWrapper<>();
        UmsAdmin userInfo = AdminUserUtil.getUserInfo();
        int userId = userInfo.getId().intValue();

        // 管理员看所有数据
        if (!userInfo.isAdmin()) {
            wrapper.eq(Order::getUserId, userId);
        }

        wrapper.eq(request.getOrderId() != null, Order::getId, request.getOrderId());
        wrapper.orderByDesc(Order::getId);
        Order order = orderService.getOne(wrapper);
        if (order == null) {
            return CommonResult.failed("Permission denied");
        }

        Integer orderId = order.getId();
        Map<Integer, List<OrderParcel>> orderParcelsMap = orderParcelService.list(new LambdaQueryWrapper<OrderParcel>()
                .eq(OrderParcel::getOrderId, orderId)).stream().collect(Collectors.groupingBy(OrderParcel::getOrderId));
        Map<Integer, Channel> channelMap = channelService.list(new LambdaQueryWrapper<Channel>()
                        .eq(Channel::getId, order.getChannelId()))
                .stream().collect(Collectors.toMap(Channel::getId, Function.identity()));

        Map<Integer, ChannelCarrier> channelCarrierMap = channelCarrierService.list(new LambdaQueryWrapper<>())
                .stream().collect(Collectors.toMap(ChannelCarrier::getId, Function.identity()));
        GetOrdersResponse getOrdersResponse = new GetOrdersResponse();
        BeanUtils.copyProperties(order, getOrdersResponse);
        getOrdersResponse.setParcels(getDraftParcels(orderParcelsMap.get(order.getId())));
        Channel channel = channelMap.get(order.getChannelId());
        if (channel != null) {
            getOrdersResponse.setServiceName(channel.getChannelName());
            ChannelCarrier channelCarrier = channelCarrierMap.get(channel.getChannelCarrierId());
            if (channelCarrier != null) {
                getOrdersResponse.setCarrierName(channelCarrier.getChannelCarrierName());

            }
        }

        return CommonResult.success(getOrdersResponse);
    }*/

    @ApiOperation("取消/作废")
    @RequestMapping(value = "/orders/cancel", method = RequestMethod.POST)
    @ResponseBody
    public CommonResult<GetOrdersResponse> cancel(@RequestBody @Validated OrderCancelRequest request) {
        LambdaQueryWrapper<Order> wrapper = new LambdaQueryWrapper<>();
        UmsAdmin userInfo = AdminUserUtil.getUserInfo();
        int userId = userInfo.getId().intValue();
        // 管理员看所有数据
        if (!userInfo.isAdmin()) {
            wrapper.eq(Order::getUserId, userId);
        }
        List<String> orderIds = request.getOrderIds();
        wrapper.in(orderIds != null, Order::getId, orderIds);
        wrapper.and(wp -> {
            wp.in(Order::getStatus,OrderStatus.DRAFT,OrderStatus.RECENT,OrderStatus.IN_TRANSIT
                    ,OrderStatus.CANCEL_REJECT
                    ,OrderStatus.FAILURE);
        });

        wrapper.orderByDesc(Order::getId);
        List<Order> orders = orderService.list(wrapper);
        if (orders.size() != orderIds.size()) {
            return CommonResult.failed("contains order not in status that can be cancel");
        }
        //订单下单成功，且创建标签时间大于七天的无法取消
        boolean isFlag = true;
        for (Order order : orders) {
            if (order.getStatus().equals(OrderStatus.FAILURE.getValue())){
                continue;
            }
            //获取当前时间30天之前的时间
            LocalDateTime time = LocalDateTime.now().minusDays(30);
            if (ObjectUtils.isNotEmpty(order.getCreateTime()) && order.getCreateTime().isBefore(time)) {
                isFlag = false;
            }
        }
        if (!isFlag) {
            return CommonResult.failed("Labels created more than 30 days ago cannot be canceled. Please contact us");
        }
        for (Order order : orders) {
            Integer status = order.getStatus();
            if (OrderStatus.DRAFT.getValue() == status) {
                order.setStatus(OrderStatus.VOIDED.getValue());
            } else {
                // 三方平台同步取消
                Channel channel = channelService.getById(order.getChannelId());
                BaseShipService baseShipService = shipFactory.getBaseShipService(channel);
                baseShipService.cancelLabel(order.getObjectId(),order.getOrderNo());
                // 状态变更为取消中
                order.setStatus(OrderStatus.CANCEL_ING.getValue());
            }
            //记录申请/作废时间
            order.setCancelTime(LocalDateTime.now());
            orderService.updateById(order);
        }
        return CommonResult.success();
    }

    @ApiOperation("批量导入订单")
    @PostMapping(value = "/upload/order")
    public CommonResult<List<EstimateRateRequest>> uploadOrder(@RequestParam("file") MultipartFile file) {
        return orderService.uploadOrder(file);
    }

    /**
     * 账单补扣
     */
    @PostMapping(value = "/upload/billed")
    public CommonResult uploadBilled(@RequestParam("file") MultipartFile file) {
        return orderService.uploadBilled(file);
    }

    /**
     * 修复线上数据bug
     */
    @ResponseBody
    @GetMapping("/test/bug")
    public CommonResult bug() {
        List<String> flags  = new ArrayList<>(3);
        String orderNo1 = "202401A0000bfbd";
        String orderNo2 = "202401A00005011";
        String str1 = "{\"result\":\"OK\",\"errorCode\":null,\"message\":\"\",\"zhMessage\":null,\"errorType\":null,\"data\":{\"objectId\":\"0743cadef46d11ee9973236224ee15c9\",\"status\":1,\"trackingNumber\":[\"1ZE066G70325055878\",\"1ZE066G70329002088\",\"1ZE066G70332898892\",\"1ZE066G70324862300\"],\"trackingUrl\":[\"https://www.ups.com/track?tracknum\\u003d1ZE066G70325055878\",\"https://www.ups.com/track?tracknum\\u003d1ZE066G70329002088\",\"https://www.ups.com/track?tracknum\\u003d1ZE066G70332898892\",\"https://www.ups.com/track?tracknum\\u003d1ZE066G70324862300\"],\"pdfUrl\":\"https://ezeeship.com/api/ezeeship/label/printLabel?objectId\\u003d0743cadef46d11ee9973236224ee15c9\",\"labelUrl\":[\"https://ezeeship.com/api/ezeeship-api/shipment/printLabel?objectId\\u003d0743cadef46d11ee9973236224ee15c9\",\"https://ezeeship.com/api/ezeeship-api/shipment/printLabel?objectId\\u003d0743cadff46d11ee9973236224ee15c9\",\"https://ezeeship.com/api/ezeeship-api/shipment/printLabel?objectId\\u003d0743cae0f46d11ee9973236224ee15c9\",\"https://ezeeship.com/api/ezeeship-api/shipment/printLabel?objectId\\u003d0743cae1f46d11ee9973236224ee15c9\"],\"invoiceUrl\":[null,null,null,null],\"rate\":50.50,\"createTime\":\"2024-04-06 23:26:00\",\"billedAmount\":0.00,\"authorizationCode\":null,\"feeDetail\":{\"baseRate\":43.63,\"Fuel\":6.87},\"originFee\":150.76,\"originFeeDetail\":{\"Fuel\":20.52,\"baseRate\":130.24},\"zone\":5,\"labelCharSet\":null,\"onlyPrintMainLabel\":null}}";
        String str2 = "{\"result\":\"OK\",\"errorCode\":null,\"message\":\"\",\"zhMessage\":null,\"errorType\":null,\"data\":{\"objectId\":\"977fcddf18e411ef93bd236b2342ace1\",\"status\":1,\"trackingNumber\":[\"776517022306\",\"776517022317\"],\"trackingUrl\":[\"https://www.fedex.com/apps/fedextrack/?action\\u003dtrack\\u0026cntry_code\\u003dus\\u0026trackingnumber\\u003d776517022306\",\"https://www.fedex.com/apps/fedextrack/?action\\u003dtrack\\u0026cntry_code\\u003dus\\u0026trackingnumber\\u003d776517022317\"],\"pdfUrl\":\"https://ezeeship.com/api/ezeeship/label/printLabel?objectId\\u003d977fcddf18e411ef93bd236b2342ace1\",\"labelUrl\":[\"https://ezeeship.com/api/ezeeship-api/shipment/printLabel?objectId\\u003d977fcddf18e411ef93bd236b2342ace1\",\"https://ezeeship.com/api/ezeeship-api/shipment/printLabel?objectId\\u003d9783505018e411ef93bd236b2342ace1\"],\"invoiceUrl\":[null,null],\"rate\":28.64,\"createTime\":\"2024-05-23 09:12:34\",\"billedAmount\":0.00,\"authorizationCode\":null,\"feeDetail\":{\"Fuel\":4.00,\"baseRate\":24.64},\"originFee\":72.30,\"originFeeDetail\":{\"baseRate\":62.20,\"Fuel\":10.1},\"zone\":8,\"labelCharSet\":null,\"onlyPrintMainLabel\":null}}";
        List<String> orderNos = new ArrayList<>(3);
        orderNos.add(orderNo1);
        orderNos.add(orderNo2);
        Map<String, String> map = new HashMap<>(3);
        map.put(orderNo1, str1);
        map.put(orderNo2, str2);
        for (String orderNo : orderNos) {
            Order order = orderService.lambdaQuery().eq(Order::getOrderNo, orderNo).one();
            String s = map.get(orderNo);
            if (ObjectUtils.isNotEmpty(order) && StringUtils.isNotBlank(s)) {
                CreateLabelResponse createLabelResponse = JSONUtil.toBean(s, CreateLabelResponse.class);
                System.out.println(createLabelResponse);
                CreateLabelResponse.Data createLabelResponseData = createLabelResponse.getData();
                String pdfUrl = createLabelResponseData.getPdfUrl();
                // 上传到oss
                String objectId = order.getObjectId();
                ossUtil.upload("pdf", objectId + ".pdf", pdfUrl);
                String newPdfUrl = Global.PRINT_LABEL_API + objectId;
                order.setPdfUrl(newPdfUrl);
                //查询包裹
                List<OrderParcel> list = orderParcelService.lambdaQuery().eq(OrderParcel::getOrderId, order.getId()).isNull(OrderParcel::getDeletedAt).list();
                List<String> trackingNumber = createLabelResponseData.getTrackingNumber();
                List<String> trackingUrl = createLabelResponseData.getTrackingUrl();
                List<String> labelUrls = createLabelResponseData.getLabelUrl();
                for (int i = 0; i < list.size(); i++) {
                    OrderParcel orderParcel = list.get(i);
                    orderParcel.setTrackingNumber(trackingNumber.get(i));
                    orderParcel.setTrackingUrl(trackingUrl.get(i));
                    String tmpName = CommonUtil.getOrderNo();
                    ossUtil.upload("pdf", tmpName + ".pdf", labelUrls.get(i));
                    String newLabelUrl = Global.PRINT_LABEL_API + tmpName;
                    orderParcel.setLabelUrl(newLabelUrl);
                }
                orderService.updateById(order);
                orderParcelService.updateBatchById(list);
            } else {
                flags.add(orderNo);
            }
        }
        return CommonResult.success(JSON.toJSONString(flags));
    }

    @ApiOperation("补扣款 根据前端传参更新")
    @PostMapping("{orderNo}")
    public CommonResult<String> updateByParamType(@PathVariable("orderNo") String orderNo, @RequestBody @Validated OrderSupplementaryRequest request) {
        return orderService.updateByParamType(request);
    }
}

